﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ClsCustomControls;
using ClsModel;
using System.Data;
using ClsUtilities.MethodInfo;
using ClsController.CatalogosNegocio;
using System.Windows.Forms.Calendar;

namespace ClsController
{
    public class ClsLogicaCitas
    {
        private ClsModelCommon model;
        private ClsLogicaNeg logicaNeg;
        private DataSet ds;
        private ErrorProvider utilErrores;
        private MethodResponse response;
        private DataTable tablaCitas;
        private List<DiasSeleccionadosCal> lista_diasPorFila;
        private DateTime fechaStart;
        private DataTable tablaCalendario;
        private PopCalendar popCalfrm;
        private List<DateTime> valoresCalendarioGen;
        private String nomPaciente;

        public ClsLogicaCitas()
        {
            model = new ClsModelCommon();
            logicaNeg = new ClsLogicaNeg();
            utilErrores = new ErrorProvider();
            tablaCalendario = new DataTable();
        }

        public bool CargarPacietnes(TextBox txtpatron, List<Control> camposAsignar)
        {
            ds = new DataSet();
            response = new MethodResponse();
            String patronBusquda =logicaNeg.ControlGetValue(txtpatron);
            DataRow filaSeleccionada;
            if (String.IsNullOrEmpty(patronBusquda))
            {
                response = model.buscarPacientes();
            }
            else
            {
                response = model.buscarPacientes(patronBusquda);
            }
            if (response.Estado)
            {
                if (response.CantFilas > 1)
                {
                    FrmSearchBox box = new FrmSearchBox();
                    box.resulBusqueda = response.ConjuntoDatos.Tables[0];
                    box.campoNombre = patronBusquda;
                    box.ShowDialog();
                    response.Estado = box.validaRestultado;
                    if (box.validaRestultado)
                    {
                        filaSeleccionada = box.valorSearch;
                        response.Estado = AsignaValorACampo(camposAsignar, filaSeleccionada);
                    }
                }
                else if (response.CantFilas == 0)
                {
                    FrmSearchBox box = new FrmSearchBox();
                    box.campoNombre = patronBusquda;
                    box.ShowDialog();
                    response.Estado = box.validaRestultado;
                    if (box.validaRestultado)
                    {
                        filaSeleccionada = box.valorSearch;
                        response.Estado = AsignaValorACampo(camposAsignar, filaSeleccionada);
                    }
                }
                else
                {
                    filaSeleccionada = response.ConjuntoDatos.Tables[0].Rows[0];
                    response.Estado = AsignaValorACampo(camposAsignar, filaSeleccionada);
                }
            }

            return response.Estado;
        }


        private bool AsignaValorACampo(List<Control> camposAsignar, DataRow filaSeleccionada)
        {
            try
            {
                int tamano_elem = camposAsignar.Count;
                for (int xx = 0; xx < tamano_elem; xx++)
                {
                    Control controlActual = camposAsignar[xx];
                    if (controlActual != null)
                    {
                        if (controlActual.GetType().Name == Catalogo.ControlType.DBTextbox.ToString())
                        {
                            DBTextbox objetoControl = (DBTextbox)controlActual;
                            objetoControl.Text = filaSeleccionada[objetoControl.DBFieldName].ToString();
                        }

                        if (controlActual.GetType().Name == Catalogo.ControlType.DBDropDownList.ToString())
                        {
                            DBDropDownList objetoControl = (DBDropDownList)controlActual;
                            objetoControl.SelectedValue = filaSeleccionada[objetoControl.DBFieldName];
                        }

                        if (controlActual.GetType().Name == Catalogo.ControlType.DBDateTimePicker.ToString())
                        {
                            DBDateTimePicker objetoControl = (DBDateTimePicker)controlActual;
                            objetoControl.Value = DateTime.Parse(filaSeleccionada[objetoControl.DBFieldName].ToString());
                        }

                        if (controlActual.GetType().Name == Catalogo.ControlType.DBLabel.ToString())
                        {
                            DBLabel objetoControl = (DBLabel)controlActual;
                            objetoControl.Text = filaSeleccionada[objetoControl.DBFieldName].ToString();
                        }
                    }

                }
                return true;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.StackTrace);
            }
         return false;
        }

        private bool ValidarFilaCitasGrid(ComboBox cmbFrec, Int16 diasSeleccionados)
        {
            string valorDiasCant = cmbFrec.SelectedValue.ToString();
            valorDiasCant = (valorDiasCant.Split('-'))[0].ToString(); ;

            if (valorDiasCant.Equals(diasSeleccionados.ToString()))
            {
                return true;
            }

            return false;
        }

        private bool ValidarFilaCitasGrid(ComboBox cmbFrec, CheckedListBox diasSeleccionados)
        {
            try
            {
                string valorDiasCant = cmbFrec.SelectedValue.ToString();
                valorDiasCant = (valorDiasCant.Split('-'))[0].ToString(); ;

                int conteo = diasSeleccionados.CheckedItems.Count;
                int valorDiasInt = int.Parse(valorDiasCant);

                if (tablaCitas.Rows.Count < 1)
                {
                    if (fechaStart.DayOfWeek.ToString() != diasSeleccionados.CheckedItems[0].ToString())
                    {
                        utilErrores.SetError(diasSeleccionados, "LA FECHA DE INICIO Y EL DIA SELECCIONADO DEBEN SER IGUALES");
                    }
                    else
                    {
                        utilErrores.SetError(diasSeleccionados, String.Empty);
                        return true;
                    }
                }
                else
                {
                    if (valorDiasInt > conteo)
                    {
                        utilErrores.SetError(diasSeleccionados, "DEBE SELECCIONAR LA CANTIDAD DE DIAS MOSTRADOS EN EL PATRON");
                    }
                    else
                    {
                        utilErrores.SetError(diasSeleccionados, String.Empty);
                        return true;
                    }

                }
            }
            catch (Exception ex)
            { 
                //LOG BIG TIME ERRORS
                MessageBox.Show(ex.ToString());
            }
            return false;
        }

        private bool CreaTablaCitas()
        {
            if (tablaCitas == null)
            {
                tablaCitas = new DataTable();
                tablaCitas.Columns.Add("FRECUENCY");
                tablaCitas.Columns.Add("SELECTED DAYS");
                tablaCitas.Columns.Add("TIMES A WEEK");
                tablaCitas.Columns.Add("WEEKS");
                tablaCitas.Columns.Add("TIME");
            }
            return true;
        }

        public bool AgregarFilasTablaCitas(ComboBox cmbFrec, CheckedListBox diasSeleccionados , DateTimePicker fechainicio,DBDateTimePicker hora)
        {
            bool resultValidacion = false;
            fechaStart = fechainicio.Value;
            if (tablaCitas == null)
                CreaTablaCitas();

            resultValidacion = ValidarFilaCitasGrid(cmbFrec, diasSeleccionados);

            if (resultValidacion)
            {
                if (tablaCitas != null)
                {
                    string valorDiasCant = logicaNeg.ControlGetValue(cmbFrec);
                    valorDiasCant = (valorDiasCant.Split('-'))[0].ToString(); ;

                    string semanas = logicaNeg.ControlGetValue(cmbFrec);
                    semanas = (semanas.Split('-'))[1].ToString(); ;

                    DataRow fila = tablaCitas.NewRow();
                    fila[0] = ((DataRowView)cmbFrec.SelectedItem).Row.ItemArray[1].ToString();
                    fila[1] = concatValores(diasSeleccionados.CheckedItems);
                    fila[2] = valorDiasCant;
                    fila[3] = semanas;
                    fila[4] = hora.Value.TimeOfDay.ToString().Substring(0,5);

                    if (lista_diasPorFila == null)
                        lista_diasPorFila = new List<DiasSeleccionadosCal>();
                    lista_diasPorFila.Add(new DiasSeleccionadosCal(diasSeleccionados.CheckedItems));

                    tablaCitas.Rows.Add(fila);
                    return true;
                }
                else
                {
                    return false;

                }
            }
            return false;
        }

        public bool ELiminaFilaTablaCitas(int filaEliminar)
        {
            try
            {
                if (tablaCitas != null && tablaCitas.Rows.Count > 0)
                {
                    tablaCitas.Rows.RemoveAt(filaEliminar);
                }
                return true;
            }
            catch (Exception ex)
            { }
            return false;
        }

        public bool LimpiaElementosCalendario()
        {
            try
            {
                if(tablaCitas != null)
                    tablaCitas.Rows.Clear();

                if (valoresCalendarioGen != null)
                    valoresCalendarioGen.Clear();

                if (lista_diasPorFila != null)
                    lista_diasPorFila.Clear();
                
                return true;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.StackTrace);
            }
            return false;
        }

        private String concatValores(String[] valores)
        {
            int x, tot_elem;
            tot_elem = valores.Length;
            String resultado = "";
            for (x = 0; x < tot_elem; x++)
            {
                resultado += valores[x] + " , ";
            }
            resultado = resultado.Remove(resultado.LastIndexOf(',')).Trim();
            return resultado;
        }

        private String concatValores(CheckedListBox.CheckedItemCollection objetos)
        {

            int x, tot_elem;
            tot_elem = objetos.Count;
            String resultado = "";
            for (x = 0; x < tot_elem; x++)
            {
                resultado += objetos[x].ToString() + " , ";
            }
            resultado = resultado.Remove(resultado.LastIndexOf(',')).Trim();
            return resultado;
        }

        public bool GeneraGridCitas(DataGridView gridCitas)
        {
            try
            {
                gridCitas.DataSource = tablaCitas;
                logicaNeg.FormateaGridFormato1(gridCitas);
                gridCitas.AutoGenerateColumns = true;
            }
            catch (Exception ex)
            {
                return false;
            }
            return true;
        }

        #region UtilidadesValidacionDiasCitas
        private DateTime getDiaByWeekName(DateTime tiempoini, String nextweekday)
        {
            int diaSemana = (int)Enum.Parse(typeof(DayOfWeek), nextweekday);
            int diaActual = (int)tiempoini.DayOfWeek;

            if (diaActual != diaSemana && diaSemana == 0)
                diaSemana = 7;
            int valorAbuscar = (diaSemana - diaActual);
            return tiempoini.AddDays(valorAbuscar);
        }

        private DateTime getThisWeekMonday(DateTime startDate)
        {
            int diaSemana = (int)startDate.DayOfWeek;
            if (diaSemana == 0)
                diaSemana = 7; 
            //Esto se hace ya que la numeracion comienza en domingo
            int valorAbuscar = diaSemana - 1;
            return startDate.AddDays(-valorAbuscar);
        }

        private DateTime getNextWeekMonday(DateTime startDate)
        {
            int diaSemana = (int)startDate.DayOfWeek;
            //Esto se hace ya que la numeracion comienza en domingo
            int valorAbuscar = diaSemana - 1;
            return startDate.AddDays(7 - valorAbuscar);
        }

        #endregion UtilidadesValidacionDiasCitas

        public bool GeneraCalendario(DBTextbox nomPac)
        {
            try
            {
                nomPaciente = logicaNeg.ControlGetValue(nomPac);
                valoresCalendarioGen = new List<DateTime>();
                DateTime date_ini_semana_act = new DateTime();
                DateTime fechaInicio = new DateTime();
                fechaInicio = fechaStart;
                int totalSemanasGeneral = 0;
                bool resultDB = true;
                //ArrayList diasSemana = new ArrayList(); ;
                //((int)Enum.Parse(typeof(ClsController.CatalogosNegocio.Catalogo.WeekDays), DateTime.Today.DayOfWeek.ToString())).ToString();

                int x, y, xtot, ytot;

                int totalFilasCalendario, totalSemanasPorFila;
                totalFilasCalendario = tablaCitas.Rows.Count - 1;

                date_ini_semana_act = getThisWeekMonday(fechaInicio);

                for (x = 0; x <= totalFilasCalendario; x++)
                {
                    totalSemanasPorFila = int.Parse(tablaCitas.Rows[x][3].ToString());
                    totalSemanasGeneral += totalSemanasPorFila;
                    for (y = 1; y <= totalSemanasPorFila; y++)
                    {
                        int cantdiaSelect, cont;
                        cantdiaSelect = lista_diasPorFila[x].getElementosAgregados;

                        for (cont = 0; cont < cantdiaSelect; cont++)
                        {
                            fechaInicio = getDiaByWeekName(fechaInicio, lista_diasPorFila[x].getElementoAt(cont));
                            string valortiempo = tablaCitas.Rows[x][4].ToString();

                            DateTime fechadummy = new DateTime();
                            fechadummy = fechaInicio.AddHours(double.Parse(valortiempo.Substring(0, 2)));
                            fechadummy = fechadummy.AddMinutes(double.Parse(valortiempo.Substring(3, 2)));
                            valoresCalendarioGen.Add(fechadummy);
                        }
                        date_ini_semana_act = getNextWeekMonday(date_ini_semana_act);
                        fechaInicio = date_ini_semana_act;
                    }
                }

                //BUCAR CITS ACTUALES
              // resultDB = logicaNeg.ValidarCalendario(fechaStart, totalSemanasGeneral, out tablaCalendario);
                resultDB = this.ValidarCalendario(fechaStart, totalSemanasGeneral, out tablaCalendario);
                if(resultDB)
                    resultDB = this.VisualizarCalendario();
                
                return resultDB;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
            return false;
        }

        public bool VisualizarCalendario()
        {
            try
            {
                if (popCalfrm == null)
                    popCalfrm = new PopCalendar();

                popCalfrm.ClearCalendarItems();
                bool fechainvalida = false;

                foreach (DateTime tiempo in valoresCalendarioGen)
                {
                    fechainvalida = false;
                    if (tablaCalendario.Rows.Count > 0)
                    {
                        String select;
                        DataRow[] filas;
                        select = " AP_PROGRAM_DATETIME >= '" + tiempo.ToString("yyyy-MM-ddTHH:mm:ss");
                        select += "' AND AP_PROGRAM_DATETIME <= '" + tiempo.ToString("yyyy-MM-ddTHH:mm:ss");
                        select += "'";
                        filas = tablaCalendario.Select(select);
                        if (filas.Length > 0)
                            fechainvalida = true;
                    }
                    popCalfrm.AddCalendarItems(tiempo, nomPaciente, fechainvalida);
                }

                popCalfrm.ShowDialog();
                return true;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
            return false;
        }

        public bool GuardarCitas(Control txtcodpaciente,Control txtDescr)
        {
            try
            {
                response = new MethodResponse(System.Reflection.MethodBase.GetCurrentMethod());
            int codPacienteG = int.Parse(logicaNeg.ControlGetValue(txtcodpaciente));
                String descr = logicaNeg.ControlGetValue(txtDescr);
            foreach (DateTime tiempo in valoresCalendarioGen)
            {
                response = model.guardaCitas(codPacienteG, descr, tiempo.ToString("yyyy-MM-dd"), tiempo.ToString("HH:mm"), tiempo);
                if (!response.Estado)
                { break; }
            }
            return response.Estado;
            }catch(Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
            return false;
        }

        public bool ValidarCalendario(DateTime fechaInic, int cantSemanas, out DataTable DiasActualesCalendario)
        {
            DiasActualesCalendario = new DataTable();
            try
            {
                response = new MethodResponse();
                response = model.buscarCalendarioProximo(fechaInic, cantSemanas);

                if (response.Estado)
                {
                    DiasActualesCalendario = response.ConjuntoDatos.Tables[0];
                }
                else
                {
                    MessageBox.Show(response.Execp.StackTrace);
                }
                return response.Estado;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
            return false;
        }
    
    }



    class DiasSeleccionadosCal
    {
        private List<String> listadoDias;
        public DiasSeleccionadosCal()
        {
            listadoDias = new List<string>();
        }

        public DiasSeleccionadosCal(CheckedListBox.CheckedItemCollection diasSeleccionados)
        {
            listadoDias = new List<string>();

            for (int x = 0; x < diasSeleccionados.Count; x++)
            {
                AgregarDias(diasSeleccionados[x].ToString());
            }
        }

        public bool AgregarDias(String valorDia)
        {
            if (listadoDias.Count < 8)
            {
                listadoDias.Add(valorDia);
                return true;
            }
            return false;
        }

        public List<String> getListaDias
        {
            get { return listadoDias; }
        }

        public int getElementosAgregados
        {
            get { return listadoDias.Count; }
        }

        public String getElementoAt(int posicion)
        {
            return listadoDias[posicion].ToString();
        }

    }
}
